import 'package:flutter/material.dart';

class ParentWidget extends StatefulWidget {
  const ParentWidget({super.key});

  @override
  State<ParentWidget> createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  // 状态，由父组件管理
  Color _boxColor = Colors.blue;
  double _boxSize = 100.0;

  void _changeAppearance() {
    setState(() {
      // 修改状态
      _boxColor = _boxColor == Colors.blue ? Colors.red : Colors.blue;
      _boxSize = _boxSize == 100.0 ? 150.0 : 100.0;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // ！！！关键在这里 ！！！
        // 每次 setState 导致 build 重执行时，都会创建一个新的 CustomBox widget 实例。
        // 这个新实例携带了新的 color 和 size 值。
        CustomBox(
          color: _boxColor, // 新值：Colors.red
          size: _boxSize,    // 新值：150.0
        ),
        ElevatedButton(
          onPressed: _changeAppearance,
          child: const Text('改变盒子'),
        ),
      ],
    );
  }
}

class CustomBox extends LeafRenderObjectWidget {
  final Color color;
  final double size;

  const CustomBox({super.key, required this.color, required this.size});

  @override
  RenderObject createRenderObject(BuildContext context) {
    print('创建 RenderObject: Color=$color, Size=$size');
    return RenderCustomBox(color: color, size: size);
  }

  @override
  void updateRenderObject(BuildContext context, RenderCustomBox renderObject) {
    // 这个方法的调用时机：
    // 父组件 ParentWidget 重建，为这个 Element 提供了新的 CustomBox(color: Colors.red, size: 150.0) widget。
    // Flutter 框架比较发现这个位置上的 Widget 仍然是 CustomBox 类型（只是属性变了），
    // 于是调用 didUpdateWidget，进而调用此方法。
    print('更新 RenderObject: '
        'Old Color=${renderObject.color}, Old Size=${renderObject._size} -> '
        'New Color=$color, New Size=$size');

    // 职责：将新 Widget 的属性同步到旧的 RenderObject 上
    renderObject.color = color;
    renderObject.mSize = size;
  }
}

class RenderCustomBox extends RenderBox {
  Color _color;
  double _size;

  RenderCustomBox({required Color color, required double size})
      : _color = color,
        _size = size;

  Color get color => _color;
  set color(Color value) {
    if (_color == value) return;
    _color = value;
    markNeedsPaint(); // 颜色变了，需要重绘
  }

  double get mSize => _size;
  set mSize(double value) {
    if (_size == value) return;
    _size = value;
    markNeedsLayout(); // 尺寸变了，需要重新布局
  }

  @override
  void performLayout() {
    size = Size(_size, _size);
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    final Paint paint = Paint()..color = _color;
    context.canvas.drawRect(offset & size, paint);
  }
}